package com.jlg.search;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.julewa.Configuration;


/**
 * @author Huang Benhua
 * @date 2011
 *
 * 
 **/

public class Searcher {
	private @Autowired Configuration conf;
	private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT);
	private String fields[] = null;
	private QueryParser parser = null;
	private Directory directory = null;
	private @PostConstruct void init(){
		String path = conf.getProperty("search.path");
		if("".equals(path) || null == path){
			throw new RuntimeException("Path of search not found");
		}
		fields = conf.getProperty("search.fields").split(",");
		parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, fields, analyzer);
		//
		File file = new File(path);
		if(!file.exists())file.mkdirs();
		try {
			directory = FSDirectory.open(file);
			if(file.list().length < 1){
				new IndexWriter(directory, analyzer, true, null).close();
			}
			parser.setDefaultOperator(QueryParser.AND_OPERATOR);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public synchronized final void createIndex(Object data){
		try{
		    IndexWriter iwriter = new IndexWriter(directory, analyzer, false, MaxFieldLength.UNLIMITED); 
		    iwriter.setMaxFieldLength(25000);
		    Document docu = createDocument(data);
		    iwriter.addDocument(docu);
		    iwriter.optimize();
		    iwriter.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public synchronized final void removeIndex(String key, String id){
		try{
			IndexReader reader = IndexReader.open(directory);
		    reader.deleteDocuments(new Term(key, id));
		    reader.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public final List<String[]> search(String key){
		List<String[]> result = new ArrayList<String[]>();
		try{
		    IndexSearcher isearcher = new IndexSearcher(directory);
		    Query query = parser.parse(key);
		    TopDocs td = isearcher.search(query, 10000);
		    for (ScoreDoc d:td.scoreDocs) {
		    	Document doc = isearcher.doc(d.doc);
		    	//
		    	String content = doc.get("content");
		    	if(content == null)content="";
		    	if(content.length() > 256)content = content.substring(0, 256) + "  <b>……</b>";
		    	result.add(new String[]{
		    			doc.get("tid"), 
		    			doc.get("uid"),
		    			doc.get("path"),
		    			doc.get("title"),
		    			content
		    	});
		    }
		    isearcher.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	    return result;
	}
	
	private Map<Class<?>, BeanInfo> beaninfos = new HashMap<Class<?>, BeanInfo>();
	private Document createDocument(Object obj){
		if(obj == null)return null;
		Class<?> c = obj.getClass();
		BeanInfo b = beaninfos.get(c);
		if(b == null){
			b = new BeanInfo(c);
			beaninfos.put(c, b);
		}
		return b.createDocument(obj);
	}

	private static final String STYLERP = "<[sS][tT][yY][lL][eE]\\s*[^<]*>.*</[sS][tT][yY][lL][eE]\\s*>";
	private static final String HTMLRP = "<[^<]+>";
	private static final String SPECIAL = "&((#[0-9]{1,10})|(0[Xx][0-9A-Fa-f]{1,10})|(0[0-7]{1,10})|([A-Za-z]{1,10}));";
	private static final String RP1 = "<[sS][cC][rR][iI][pP][tT]\\s*[^<]*>.*</[sS][cC][rR][iI][pP][tT]\\s*>";
	public static void main(String a[]){
		String txt = "b<Script><!--, -->>>c</script>";
		System.out.println(txt.replaceAll(RP1, "\t"));
		//System.out.println(txt.replaceAll("<[^<]+>", "\t"));
	}
	
}
